import { Color, EventTouch, Vec2, v2 } from "cc"
import { IVector2, Maths, NodeHelper, Vector2, _audio, _gameType, _logic, _scene, _timer, _ui, winCenterPostion } from "../../../main/script/Main"
import { Scene } from "../Scene"
import { CSceneData, ILogicNuoData } from "../../../main/script/module/define/LogicDefine"
import { SelectionEntity } from "../entity/SelectionEntity"
import { EGameType } from "../../../main/script/module/define/GameTypeDefine"


const v2TTouchMove = new Vec2()
const v2T2 = new Vector2()
const v2T = new Vec2()
const v2T3 = new Vec2()

export class NuoSceneLogic {

    private _touchStartPos = new Vec2()
    private _startData: ILogicNuoData = null!
    public _moveDatas: ILogicNuoData[] = []
    public _moveRemoveDatas: ILogicNuoData[] = []
    public _moveAllDatas: ILogicNuoData[] = []
    private _moveIsStart = false
    private _moveIsStartOut = false
    private _moveDataRemoveCount = -1
    public touchMoveDir = new Vector2()
    public _selection: SelectionEntity = null!
    private _startDataPos = new Vector2()
    private _moveSpaceAll = new Vector2()
    private _moveSpaceCur = new Vector2()

    private _moveDataRemoveCountDis = -1

    private _moveSpaceAll2 = new Vector2()
    private _moveSpaceCur2 = new Vector2()
    private _moveSpaceCur3 = new Vector2()

    private get scene() { return _scene.getCurrent<Scene>() }

    public create() {

        let datas = _logic.nuo.data.datas
        this.scene.startAnim(
            datas.length,
            (_index) => {
                let data = datas[_index]
                data.entity = this.scene.entityMgr.createCubeNuo(data, this.scene.animLoadDir.subCount(), 0)
            },
            (indexs) => {
                this.scene.getIndexs(_logic.size, indexs, 0)
            },
            () => {
                for (let dataEntity of datas) {
                    dataEntity.entity.startAnim()
                }

                _timer.once(this, () => {
                    _ui.blockTouchEvent(false)
                    this.scene.isLoadComplete = true
                    this.scene.guide()

                    this.scene.cBorder.active = true
                    NodeHelper.setSize(
                        this.scene.cBorder,
                        _logic.size.x * _logic.cubeSize.width + 36,
                        _logic.size.y * _logic.cubeSize.height + 46,
                    )
                    NodeHelper.setPositionY(this.scene.cBorder, _logic.offsetY, false)
                }, 0.2)

            }
        )
    }

    public touchStart(e: EventTouch) {
        e.getUILocation(this._touchStartPos)
        this._startData = this.touchData(e)

        if (this._startData) {
            this._startData.entity.getUIPosition(this._startDataPos)
            this._selection = this.scene.entityMgr.createSelectionNuo(this._startData)
        }
        this.stopTouchMove(false)
    }

    private stopTouchMove(removeBorder = true) {
        for (let vdata of this._moveAllDatas) {
            vdata.entity.touchMoveStop()
        }
        this._moveDatas.length = 0
        this._moveRemoveDatas.length = 0
        this._moveAllDatas.length = 0
        this._moveIsStart = false
        this._moveIsStartOut = false
        this.touchMoveDir.set()

        if (removeBorder) {
            if (this._selection) {
                this.scene.entityMgr.remove(this._selection)
                this._selection = null!
            }
        }
    }

    public touchEnd(event: EventTouch) {
        let _startData = this._startData
        this._startData = null!

        if (_startData) {
            if (_gameType.type == EGameType.nuoLevel) {
                _logic._nuoLevel.subStep()
            }

            let moves = [...this._moveDatas]
            // 拖动
            if (moves.length > 0) {
                let dir = Vector2.set(v2T2, this.touchMoveDir)

                let ratio = this._moveSpaceCur.len() / this._moveSpaceAll.len()
                let count = Math.round(ratio * this._moveDataRemoveCount)

                // 交换位置检测
                let moveDatas = _logic.nuo.moveChangeSame(dir, moves, count)
                if (moveDatas) {
                    for (let vmove of moves) {
                        vmove.entity.touchMoveStop()
                    }
                    this.remove(
                        moves[0],
                        moveDatas[0] == moves[0].dataIndex ? _logic.nuo.data.datas[moveDatas[1]] : _logic.nuo.data.datas[moveDatas[0]]
                    )
                }
            } else {
                let _data = this.touchData(event)
                if (_data && _startData == _data) {
                    // 检验是否可消除
                    let moveDatas = _logic.nuo.getStaticSameRemove(_data)
                    if (moveDatas) {
                        this.remove(
                            _data,
                            moveDatas[0] == _data.dataIndex ? _logic.nuo.data.datas[moveDatas[1]] : _logic.nuo.data.datas[moveDatas[0]]
                        )
                    }
                }
            }
        }
        this.stopTouchMove()
    }

    public remove(_start: ILogicNuoData, _end: ILogicNuoData) {
        this.scene.clearTips()

        Vector2.add(v2T, _start.rect.center, winCenterPostion())
        Vector2.add(v2T2, _end.rect.center, winCenterPostion())
        _ui.showLine(v2T, v2T2, Color.RED)
        _timer.once(this, () => {
            _ui.hideLine()
        }, .3)

        let _isScaleX = Maths.isRandom(0.5)
        let _isLeft = _start.rect.x < _end.rect.x
        _start.entity.remove(_isLeft, _isScaleX)
        _end.entity.remove(!_isLeft, _isScaleX)

        _logic.nuo.checkNoSame()
        this.scene.removeComplete()
    }


    public touchMove(event: EventTouch) {
        if (!this._startData) {
            return
        }

        event.getUILocation(v2TTouchMove)

        let _raito = 4
        if (Vector2.distance(v2TTouchMove, this._touchStartPos) > _raito) {
            this.startMove(event)
        }

        let _dis = -1
        if (!this._moveIsStartOut || this._moveIsStart) {
            this._startData.entity.getUIPosition(v2T2, this._startData.entity.touchMovePosTarget)
            _dis = Vector2.distance(v2T2, this._startDataPos)
        }

        // 回到中心点
        if (this._moveIsStart) {
            if (this._moveIsStartOut)
                if (_dis < _raito) {
                    this._touchStartPos.set(v2TTouchMove)
                    this.stopTouchMove()
                }
        }

        // 已出去
        if (!this._moveIsStartOut) {
            if (_dis >= _raito) {
                this._moveIsStartOut = true
            }
        }
    }

    private startMove(e: EventTouch) {

        let isStart = false
        if (!this._moveIsStart) {

            this.getMoveDir(v2TTouchMove)
            let { datas, remove } = _logic.nuo.getMoveDatas(this._startData, this.touchMoveDir)
            if (remove.length > 0) {
                isStart = true
                // console.log("开始拖动", remove.length, datas.length)
                this._moveIsStart = true
                this._moveSpaceCur.set()
                this._moveSpaceAll.x = this.touchMoveDir.x * _logic.cubeSize.x * remove.length
                this._moveSpaceAll.y = this.touchMoveDir.y * _logic.cubeSize.y * remove.length

                let _startData = this._startData
                _startData.entity.getUIPosition(this._moveSpaceCur2)

                Vector2.set(v2T, _startData.rect.center)

                this._moveSpaceCur3.set(this._moveSpaceCur2)

                v2T.x += this._moveSpaceAll.x
                v2T.y += this._moveSpaceAll.y
                _startData.entity.getUIPosition(this._moveSpaceAll2, v2T)

                // console.log(this._moveSpaceAll2.toString(), this._moveSpaceCur2.toString())

                this._moveDataRemoveCountDis = Vector2.distance(this._moveSpaceCur2, this._moveSpaceAll2)

                this._moveDataRemoveCount = remove.length
                this._moveDatas.push(...datas)
                this._moveRemoveDatas.push(...remove)

                this._moveAllDatas.push(...datas, ...remove)
                // 开始拖动
                for (let v of this._moveDatas)
                    v.entity.touchMoveStartBefore()
                for (let v of this._moveDatas)
                    v.entity.touchMoveStart()
            }
        }

        if (this._moveRemoveDatas.length > 0) {

            Vector2.sub(v2T, v2TTouchMove, winCenterPostion())

            Vector2.clampf(this._moveSpaceCur3, v2T, this._moveSpaceCur2, this._moveSpaceAll2)

            let dis = Vector2.distance(this._moveSpaceCur2, this._moveSpaceCur3)
            let ratio = dis / this._moveDataRemoveCountDis

            this._moveSpaceCur.x = ratio * this._moveSpaceAll.x
            this._moveSpaceCur.y = ratio * this._moveSpaceAll.y

            for (let v of this._moveDatas)
                v.entity.touchMoveing(this._moveSpaceCur)

            // 移动背面
            let removeCount = this._moveRemoveDatas.length

            for (let i = 0; i < removeCount; i++) {
                let data = this._moveRemoveDatas[i]

                let _ratio = (i + 1) / removeCount
                let _beforeRatio = i / removeCount

                let pos: IVector2 = null!
                if (ratio >= _beforeRatio) {
                    if (ratio <= _ratio) {
                        let centerRatio = Maths.lerp(_ratio, _beforeRatio, .5)
                        if (ratio > centerRatio)
                            pos = this._moveAllDatas[i].rect.center
                        else
                            pos = data.rect.center
                    }
                    else
                        pos = this._moveAllDatas[i].rect.center
                }
                else
                    pos = data.rect.center

                if (!isStart)
                    if (!Vector2.equals(data.entity.touchMovePosTarget, pos, 1))
                        _audio.play(CSceneData.audio.drag)

                data.entity.touchMoveRemove(pos)
            }
        }
    }

    public touchClear() {
        this.stopTouchMove()
    }

    private getMoveDir(curPos: IVector2) {
        let _angle = Vector2.angle360(this._touchStartPos, curPos)
        if (_angle >= 45 && _angle < 135) {
            this.touchMoveDir.set(0, 1)
        } else if (_angle >= 135 && _angle < 225) {
            this.touchMoveDir.set(-1, 0)
        } else if (_angle >= 225 && _angle < 315) {
            this.touchMoveDir.set(0, -1)
        } else {
            this.touchMoveDir.set(1, 0)
        }
    }


    private touchData(e: EventTouch): ILogicNuoData {
        this.scene.getTouchPos(e)
        for (let logicData of _logic.nuo.data.datas) {
            if (!logicData)
                continue
            if (!logicData.entity)
                continue
            if (logicData.isRemove)
                continue

            if (logicData.rect.contains(this.scene.touchMovePos))
                return logicData
        }

        return null!
    }


}